/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.entitygen;

import com.inspur.edp.caf.generator.BaseGenerator;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.field.FieldGenerator;
import com.inspur.edp.caf.generator.item.ClassGenerator;
import com.inspur.edp.caf.generator.item.ClassGeneratorContext;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.attr.CefEntityAttribute;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.gencommon.MediateType;
import com.inspur.edp.cef.gencommon.ReflectionUtils;
import com.inspur.edp.cef.generator.apiGenerator.CefApiGeneratorContext;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.method.DataTypeGetVersionGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.method.GetResInfoGenerator;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import java.util.ArrayList;
import org.eclipse.jdt.core.dom.Modifier;

public abstract class DataTypeImpGenerator extends ClassGenerator {

  protected EntityGeneratorContext ParentContext;
  protected String CefDataTypeName;
  private MediateType allInterfaceType;
  protected IGspCommonDataType dataType;

  protected DataTypeImpGenerator(EntityGeneratorContext parContext, IGspCommonDataType node) {
    super(parContext.getProjContext().getCompilationUnitInfo());
    this.dataType = node;
    ParentContext = parContext;
//    setEntityTypeInfoToMgrType(ParentContext, nodeCode, entityTypeInfo);
    ParentContext.getProjContext().getEntityMediateTypes()
        .put(dataType.getCode(), new MediateType("", getName()));
  }

  private MediateType getAllInterfaceType() {
    if (allInterfaceType == null) {
      allInterfaceType = ((CefApiGeneratorContext) ParentContext.getProjContext().getCefGenContext()
          .getApiGenContext()).getEntityAllInterfaceTypes().get(dataType.getCode());
    }
    return allInterfaceType;
  }

  public DataTypeImpContext getDataTypeImplContext() {
    return (DataTypeImpContext) super.getContext();
  }

  protected boolean hasDtm() {
    return true;
  }

  protected boolean hasVal() {
    return true;
  }

  @Override
  protected final ClassGeneratorContext createClassInfoContext() {
    DataTypeImpContext context = getDataTypeImpContext();
    context.setParentContext(ParentContext);
    context.setClassName(getName());
    context.setDataType(dataType);
    context.setNodeCode(dataType.getCode());
    //TODO 子类中给ParentContext.Main和nodecode赋值
    return context;
  }

  protected DataTypeImpContext getDataTypeImpContext() {
    return new DataTypeImpContext();
  }

  public boolean getGenData() {
    return true;
  }
  private final static String resInfoName = "entityResInfo";
  @Override
  protected java.util.ArrayList<BaseGenerator> createClassExtendChildGenrators() {
    java.util.ArrayList<BaseGenerator> rez = new java.util.ArrayList<BaseGenerator>();
    if (getGenData()) {
      EntityDataImplGenerator cefDataGen = getMainDataGenerator();
      getDataTypeImplContext().setCefDataTypeName(CefDataTypeName = cefDataGen.getName());
      rez.add(cefDataGen);
    }


//    java.util.ArrayList<RTDtmAssemblerGenerator> dtms = createRTDtmAssemblerGenerator();
//    java.util.ArrayList<RTValAssemblerGenerator> vals = createValtmAssemblerGenerator();
//    if (dtms != null) {
//      ParentContext.getProjContext().addImport(IDetermination.class.getName());
//      rez.addAll(dtms);
//    }
//    if (vals != null) {
//      ParentContext.getProjContext().addImport(IValidation.class.getName());
//      rez.addAll(vals);
//    }

    return rez;
  }
//不需要了。
//  protected abstract java.util.ArrayList<RTDtmAssemblerGenerator> createRTDtmAssemblerGenerator();
//
//  protected abstract java.util.ArrayList<RTValAssemblerGenerator> createValtmAssemblerGenerator();

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getAccessModifier() {
    ArrayList<Modifier.ModifierKeyword> list = new ArrayList<>();
    list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
    return list;
  }

  @Override
  protected ArrayList<TypeInfo> addParentInterfaces() {
    ArrayList<TypeInfo> list = new ArrayList<>();
    TypeInfo info = new TypeInfo(getAllInterfaceType().getFullName());
    list.add(info);
    addExtendParentInterfaces(list);
    return list;
  }


  protected abstract void addExtendParentInterfaces(ArrayList<TypeInfo> parents);

  @Override
  protected TypeInfo setParentClass() {
    return new TypeInfo(getParentClass());
  }


  protected abstract java.lang.Class getParentClass();
//  {
//    return CefDataType.class;
//  }

  @Override
  protected final java.util.ArrayList<ClassMethodGenerator> createMethodGenerators() {
    java.util.ArrayList<ClassMethodGenerator> methodGens = super.createMethodGenerators();

    if (methodGens == null) {
      methodGens = new java.util.ArrayList<ClassMethodGenerator>();
    }

    ClassMethodGenerator assGen;

    if (hasDtm()) {
      //默认时机CreateDtmAssembler方法
      assGen = getCreateAfterModifyDtmAssMethodGenerator();
      if (assGen != null) {
        methodGens.add(assGen);
      }
      assGen = getCreateAfterCreateDtmAssMethodGenerator();
      if (assGen != null) {
        methodGens.add(assGen);
      }
      assGen = getCreateBeforeSaveDtmAssMethodGenerator();
      if (assGen != null) {
        methodGens.add(assGen);
      }
      //其他时机CreateDtmAssembler方法
      addExtendDtmAssMethodGenerator(methodGens);
    }

    if (hasVal()) {
      //默认时机CreateValidationAssembler方法
      assGen = getCreateAfterModifyValAssMethodGenerator();
      if (assGen != null) {
        methodGens.add(assGen);
      }
      assGen = getCreateBeforeSaveValAssMethodGenerator();
      if (assGen != null) {
        methodGens.add(assGen);
      }
      //其他时机CreateValidationAssembler方法
      addExtendValAssMethodGenerator(methodGens);
    }

    //②其他自定义方法
    addExtendMethodGenerator(methodGens);

    //if (GenData)
    //methodGens.add(createAssignDefaultValueGenerator());
    methodGens.add(new DataTypeGetVersionGenerator());
    ClassMethodGenerator cacheInfoMethodGenerator = getDataTypeCacheInfoMethodGenerator();
    if(cacheInfoMethodGenerator != null) {
      methodGens.add(cacheInfoMethodGenerator);
    }
    return methodGens;
  }

  protected abstract ClassMethodGenerator getDataTypeCacheInfoMethodGenerator();

//  protected ClassMethodGenerator createAssignDefaultValueGenerator() {
//    return null;
//  }

  //#region CreateDtmAssembler
  protected abstract ClassMethodGenerator getCreateAfterModifyDtmAssMethodGenerator();

  protected abstract ClassMethodGenerator getCreateAfterCreateDtmAssMethodGenerator();

  protected abstract ClassMethodGenerator getCreateBeforeSaveDtmAssMethodGenerator();

  protected void addExtendDtmAssMethodGenerator(
      java.util.ArrayList<ClassMethodGenerator> methodGens) {
  }

  protected abstract ClassMethodGenerator getCreateAfterModifyValAssMethodGenerator();

  protected abstract ClassMethodGenerator getCreateBeforeSaveValAssMethodGenerator();

  protected void addExtendValAssMethodGenerator(
      java.util.ArrayList<ClassMethodGenerator> methodGens) {
  }

  @Override
  protected String getName() {
    return String.format("%s_%s%s",
        ParentContext.getProjContext().getCefGenContext().getMetadata().getHeader().getCode(),
        dataType.getCode(),
        "Entity");
  }

  protected void addExtendMethodGenerator(java.util.ArrayList<ClassMethodGenerator> generators) {
  }

  private EntityDataImplGenerator getMainDataGenerator() {
    MediateType baseDataType = ParentContext.getProjContext().getCefGenContext().getRootDataInterfaceType();
    return getDataGenerator(baseDataType);
  }

  protected abstract EntityDataImplGenerator getDataGenerator(MediateType baseType);

  @Override
  protected java.util.ArrayList<ClassMethodGenerator> createConstructorGenerators() {
    //TODO CefEntity构造函数中给CefData和ID初始化， ValueObject中给CefData初始化
    return new java.util.ArrayList<ClassMethodGenerator>(java.util.Arrays
        .asList(getConstructorGenerator(getName(), CefDataTypeName)));
  }

  protected abstract ClassMethodGenerator getConstructorGenerator(String typeName, String dataName);
  //#endregion


  @Override
  protected ArrayList<FieldGenerator> createFieldGenerator() {
    ArrayList<FieldGenerator> list= super.createFieldGenerator();
    if(list ==null)
      list =new ArrayList<>();
    FieldGenerator cacheInfoFieldGenerator = getDataTypeCacheInfoFieldGenerator();
    if(cacheInfoFieldGenerator != null) {
      list.add(cacheInfoFieldGenerator);
    }
    return list;
  }

  protected abstract FieldGenerator getDataTypeCacheInfoFieldGenerator();
}
